package com.use.utils.controller;

import org.springframework.core.io.InputStreamResource;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.StreamingResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.Collections;
import java.util.List;


@RestController
    public class FileController {

        // 大文件路径（替换为实际路径）
        private static final String FILE_PATH = "/Users/a123456/Downloads/bigFIle.bin";

        @GetMapping("/download")
        public ResponseEntity<InputStreamResource> downloadFile(
                HttpServletRequest request,
                @RequestHeader(value = "Range", required = false) String rangeHeader) throws IOException {

            File file = new File(FILE_PATH);
            long fileLength = file.length();

            // 准备基础响应头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
            headers.setContentDisposition(
                    ContentDisposition.attachment().filename("downloaded-file.dat").build());
//            headers.setAcceptRanges(Collections.singletonList(RangeUnit.BYTES));

            // 无 Range 请求时返回完整文件
            if (rangeHeader == null) {
                headers.setContentLength(fileLength);
                return ResponseEntity.ok()
                        .headers(headers)
                        .body(new InputStreamResource(new FileInputStream(file)));
            }

            // 解析 Range 请求
            List<HttpRange> ranges;
            try {
                ranges = HttpRange.parseRanges(rangeHeader);
            } catch (IllegalArgumentException e) {
                return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
            }

            // 仅处理单个范围请求
            if (ranges.size() != 1) {
                headers.set("Content-Range", "bytes */" + fileLength);
                return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
                        .headers(headers)
                        .build();
            }

            HttpRange range = ranges.get(0);
            long start = range.getRangeStart(fileLength);
            long end = range.getRangeEnd(fileLength);
            long contentLength = end - start + 1;

            // 验证范围合法性
            if (start >= fileLength || end >= fileLength || start > end) {
                headers.set("Content-Range", "bytes */" + fileLength);
                return ResponseEntity.status(HttpStatus.REQUESTED_RANGE_NOT_SATISFIABLE)
                        .headers(headers)
                        .build();
            }

            // 设置范围响应头
            headers.setContentLength(contentLength);
            headers.set("Content-Range", "bytes " + start + "-" + end + "/" + fileLength);

            // 创建带范围的文件流
            RandomAccessFile raf = new RandomAccessFile(file, "r");
            raf.seek(start);
            InputStream inputStream = new InputStream() {
                private long bytesRead = 0;

                @Override
                public int read() throws IOException {
                    if (bytesRead >= contentLength) return -1;
                    int b = raf.read();
                    if (b != -1) bytesRead++;
                    return b;
                }

                @Override
                public int read(byte[] b, int off, int len) throws IOException {
                    if (bytesRead >= contentLength) return -1;
                    int adjustedLen = (int) Math.min(len, contentLength - bytesRead);
                    int read = raf.read(b, off, adjustedLen);
                    if (read != -1) bytesRead += read;
                    return read;
                }

                @Override
                public void close() throws IOException {
                    raf.close();
                }
            };

            return ResponseEntity.status(HttpStatus.PARTIAL_CONTENT)
                    .headers(headers)
                    .body(new InputStreamResource(inputStream));
        }


    }
